package com.lapula.crazyface.entity;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.Log;

import com.lapula.crazyface.D;
import com.lapula.crazyface.util.FaceEmotion;
import com.lapula.crazyface.util.FaceEmotion.MFace;

public abstract class Emotion {
	public final static int BASED_POINT_LEFT_EYE = 0;
	public final static int BASED_POINT_RIGHT_EYE = 1;
	public final static int BASED_POINT_EYE_MIDDLE = 2;

	public final float FACE_RATIO = 150.0f / 320.0f;

	protected Context context;

	protected List<ExpressionItem> expressioItems = new ArrayList<ExpressionItem>();

	public Emotion(Context c) {
		context = c;
		init();
	}

	public List<EmotionItem> render(List<FaceEmotion.MFace> faces, Bitmap screen) {
		List<EmotionItem> items = new ArrayList<EmotionItem>();
		float ratio = 1.0f;
		for (FaceEmotion.MFace f : faces) {
			ratio = f.face.eyesDistance() / D.I().getImageSize().width / FACE_RATIO;
			for (ExpressionItem ei : expressioItems) {
				Bitmap bitmap = ei.nextFrame();
				Matrix matrix = new Matrix();
				if (ei.mode == ExpressionItem.MODE_NORMAL){
					PointF basedPoint = getBasedPoint(f, ei.basedPoint);
					matrix.postScale(ratio, ratio);
					matrix.postTranslate(basedPoint.x, basedPoint.y);
					matrix.postTranslate(bitmap.getWidth() * ratio * ei.offset.horizontal, bitmap.getHeight() * ratio * ei.offset.vertical);
				} else if (ei.mode == ExpressionItem.MODE_FULL_SCREEN){
					PointF basedPoint = new PointF(screen.getWidth() / 2, screen.getHeight() / 2);
					ratio = (float)screen.getWidth() / bitmap.getWidth();
					if (ratio > (float)screen.getHeight() / bitmap.getHeight()){
						ratio = (float)screen.getHeight() / bitmap.getHeight();
					}
					matrix.postScale(ratio, ratio);
					matrix.postTranslate(D.I().left, D.I().top);
				}
				EmotionItem item = new EmotionItem(bitmap, matrix);
				items.add(item);
			}
		}

		return items;
	}

	protected PointF getBasedPoint(MFace f, int p) {
		switch (p) {
		case BASED_POINT_LEFT_EYE:
			return f.leftEye;
		case BASED_POINT_RIGHT_EYE:
			return f.rightEye;
		case BASED_POINT_EYE_MIDDLE:
			PointF mid = new PointF();
			f.face.getMidPoint(mid);
			return mid;
		default:
			return f.leftEye;
		}
	}

	abstract protected void init();

	/**
	 * 画在脸上的元素
	 * 
	 * @author nevor
	 * 
	 */
	public class EmotionItem {
		public Bitmap bitmap;
		public Matrix matrix;

		public EmotionItem(Bitmap b, Matrix m) {
			bitmap = b;
			matrix = m;
		}
	}

	public class OffsetRatio {
		public float horizontal;
		public float vertical;

		public OffsetRatio(float h, float v) {
			horizontal = h;
			vertical = v;
		}
	}

	public class ExpressionItem {
		final public static int MODE_NORMAL = 0;
		final public static int MODE_FULL_SCREEN = 1;

		private final int FRAME_STEP = 2;

		// 渲染模式，现分普通模式和全屏模式
		public int mode = 0;

		private int basedPoint;
		private List<Bitmap> pics;
		private OffsetRatio offset;

		private int frameIndex = -0; // 第几帧
		private float frameIndexF = 0; // 辅助一个表情帧画在若干个画面帧的数据

		public ExpressionItem(List<Bitmap> pics, OffsetRatio offset, int basedPoint) {
			this.pics = pics;
			this.offset = offset;
			this.basedPoint = basedPoint;
		}

		public Bitmap nextFrame() {
			frameIndex = (frameIndex + 1) % (FRAME_STEP * pics.size());
			return pics.get(frameIndex / 2);
		}

		public int getBasedPoint() {
			return basedPoint;
		}

		public List<Bitmap> getPics() {
			return pics;
		}

		public OffsetRatio getOffset() {
			return offset;
		}
	}
}
